import Cp from "child_process";
import { CSV, splitArrByCol } from "../common/index";
import { cpus } from "../workers";
const { csvInterpolateSync, getCsvParams } = CSV;

/**
 * @param msg 键名为就是函数名，值就是向函数发送的参数
 * @returns 返回函数名和函数运行结果
 */
function csvRunChild(msg: Object): Promise<{
  funcName: string;
  result: any;
}> {
  return new Promise((resolve, reject) => {
    let child = Cp.fork(__filename);
    child.on("message", (msg: any) => resolve(msg));
    child.on("error", reject);
    child.send({ ...msg, isCsvInterpolator: true });
  });
}

export interface CsvInterpolateResult {
  final: CSV.FinalResult.Row[];
  csvParams: CSV.GetCsvParams.Result;
}

/**
 * 进行csvInterpolation
 * @param option
 * @returns
 */
async function csvInterpolateChild(
  option: CSV.GetCsvParams.Option
): Promise<CsvInterpolateResult> {
  let cpuNum = cpus();
  let csvParams = (await csvRunChild({ getCsvParams: option })).result;
  let { result: indexed } = await csvRunChild({ getIndexedSync: csvParams }); // let indexed = CSV.getIndexedSync(csvParams);
  let allFrames = CSV.getAllFrames(csvParams);
  let allFramesSplitted = splitArrByCol(allFrames, cpuNum);
  let promises = Promise.all(
    allFramesSplitted.map((e) =>
      csvRunChild({ interpolateRowsSync: { indexed, allFrames: e } })
    )
  );
  let final = (await promises).map((e) => e.result).flat(1);
  console.log(`----- interpolation completed -----`);
  return { final, csvParams };
}

/**
 * 通过调用子进程对csv文件进行interpolation
 * @param option 选项
 * @returns
 */
export async function csvInterpolate(
  option: CSV.GetCsvParams.Option
): Promise<CsvInterpolateResult> {
  let res = await csvRunChild({ csvInterpolateChild: option });
  return res.result;
}

// 作为child_process时处理函数
process.on("message", async (options: { [key: string]: any }) => {
  if (options.isCsvInterpolator) {
    for (let key in options) {
      if (key === "isCsvInterpolator") continue;
      // console.log(`----- interpolation child process start @${key} -----`);
      let ns = { ...CSV, csvInterpolateChild };
      // @ts-ignore
      process.send({
        funcName: key, // @ts-ignore
        result: await ns[key](options[key]),
      });
      // console.log(`----- interpolation child process ended @${key} -----`);
    }
  }
  process.exit(0);
});

export { csvInterpolateSync, getCsvParams };
